package org.vs.service.impl;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import org.vs.service.SSEService;

import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
@Service
public class SSEServiceImpl implements SSEService {
    private static final Map<String, SseEmitter> sseEmitterMap = new ConcurrentHashMap<>();

    @Override
    public SseEmitter connect(String id) {
        try {
            // 设置超时时间，0表示不过期。默认30秒
            SseEmitter sseEmitter = new SseEmitter(30 * 1000L);
            sseEmitter.send(SseEmitter.event().id(id).data(""));
            sseEmitter.onCompletion(completionCallBack(id));
            sseEmitter.onTimeout(timeoutCallBack(id));
            sseEmitterMap.put(id, sseEmitter);
            return sseEmitter;
        } catch (Exception e) {
        }
        return null;
    }

    @Override
    public boolean sendMessage(String id, String message) {
        if (sseEmitterMap.containsKey(id)) {
            SseEmitter sseEmitter = sseEmitterMap.get(id);
            try {
                sseEmitter.send(SseEmitter.event().id(id).data(message));
                return true;
            } catch (Exception e) {
                sseEmitterMap.remove(id);
                sseEmitter.complete();
                return false;
            }
        } else {
        }
        return false;
    }

    public void delete(String id) {
        remove(id);
    }

    private Runnable completionCallBack(String id) {
        return () -> {
            remove(id);
        };
    }

    private Throwable errorCallBack(String id) {
        remove(id);
        return new Throwable();
    }

    private Runnable timeoutCallBack(String userId) {
        return () -> {
            remove(userId);
        };
    }

    private void remove(String id) {
        if (sseEmitterMap.containsKey(id)) {
            SseEmitter sseEmitter = sseEmitterMap.get(id);
            sseEmitterMap.remove(id);
            sseEmitter.complete();
        } else {
        }
    }
}
